package com.bestcem.xm.user.service.impl;

import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.AuthErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.exception.GrpcCallFailedException;
import com.bestcem.xm.common.core.sequence.dao.SequenceDao;
import com.bestcem.xm.common.core.sequence.entity.SequenceDO;
import com.bestcem.xm.common.core.sequence.entity.SequenceEntity;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.component.security.dto.TokenDTO;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.user.constant.UserCacheKeyConstant;
import com.bestcem.xm.user.constant.UserGroupConstant;
import com.bestcem.xm.user.enums.*;
import com.bestcem.xm.user.grpc.service.param.GroupLevelSyncParam;
import com.bestcem.xm.user.grpc.service.param.GroupSyncParam;
import com.bestcem.xm.user.grpc.service.param.OpenGroupTreeByAsyncParam;
import com.bestcem.xm.user.grpc.service.param.OpenGroupTreeParam;
import com.bestcem.xm.user.handler.GroupImportHandler;
import com.bestcem.xm.user.handler.excel.read.listener.OpenGroupReadListener;
import com.bestcem.xm.user.handler.excel.read.listener.OpenLevelReadListener;
import com.bestcem.xm.user.mq.info.group.GroupNameInfo;
import com.bestcem.xm.user.mq.info.group.StoreInfo;
import com.bestcem.xm.user.mq.send.biz.UserMessageSendService;
import com.bestcem.xm.user.service.*;
import com.bestcem.xm.user.service.dto.PageResponseDTO;
import com.bestcem.xm.user.service.dto.group.*;
import com.bestcem.xm.user.service.dto.user.OrganizationDTO;
import com.bestcem.xm.user.service.dto.user.UserDTO;
import com.bestcem.xm.user.util.business.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 用户层级业务service
 *
 * @author wangyunyun <yunyun.wang@idiaoyan.com>
 * @version v1.0
 * @date 2021/12/29 10:30
 */
@Slf4j
@Service
public class UserGroupBusinessServiceImpl implements UserGroupBusinessService {

    @Autowired
    private UserGroupLevelService userGroupLevelService;

    @Autowired
    private UserGroupService userGroupService;

    @Autowired
    private GroupSequenceUtil groupSequenceUtil;

    @Autowired
    private GroupImportHandler groupImportHandler;

    /*@Resource
    private OssService ossService;*/

    @Autowired
    private StorageService storageService;

    @Autowired
    private UserGroupImportRecordService userGroupImportRecordService;

    //@Autowired
    //private UserGroupMessageSender userGroupMessageSender;

    @Resource
    private UserMessageSendService userMessageSendService;

    @Autowired
    private UserUserGroupService userUserGroupService;

    @Autowired
    private OrganizationService organzationService;

    @Autowired
    private SequenceDao sequenceDao;

    @Autowired
    private UserService userService;

    @Resource
    private SequenceService sequenceService;

    @Resource
    private GroupLockUtil groupLockUtil;

    @Resource
    private UserCacheUtil userCacheUtil;

    @Override
    public ServiceResult<List<IdRelationDTO>> listSampleGroupLevelIds(String srcOrgId, String dstOrgId) {
        // 参数校验
        if (StringUtils.isBlank(srcOrgId) || StringUtils.isBlank(dstOrgId)) {
            return ServiceResult.fail("参数不能为空");
        }

        // 查询源公司id下的所有层级
        ServiceResult<List<UserGroupLevelDTO>> serviceResult = userGroupLevelService.listByOrgId(srcOrgId);
        if (!serviceResult.isSuccess()) {
            return ServiceResult.fail(serviceResult.getMsg());
        }

        List<UserGroupLevelDTO> srcLevels = serviceResult.getData();
        if (CollectionUtils.isEmpty(srcLevels)) {
            // 源公司层级集合为空, 直接返回空集合
            return ServiceResult.success(Collections.emptyList());
        }

        // 查询目标公司id下的所有层级
        ServiceResult<List<UserGroupLevelDTO>> serviceResultDst = userGroupLevelService.listByOrgId(dstOrgId);
        if (!serviceResultDst.isSuccess()) {
            return ServiceResult.fail(serviceResultDst.getMsg());
        }

        List<UserGroupLevelDTO> dstLevels = serviceResultDst.getData();
        if (CollectionUtils.isEmpty(dstLevels)) {
            // 目标公司层级集合为空, 直接返回空集合
            return ServiceResult.success(Collections.emptyList());
        }

        // 遍历目标公司下的所有层级: 比较目标公司层级和源公司层级的名称,如果相同则设置为id_relations一个元素
        List<IdRelationDTO> idRelations = buildLevelIdRelations(srcLevels, dstLevels);
        // 遍历成功返回id_relations
        return ServiceResult.success(idRelations);
    }

    @Override
    public ServiceResult<List<IdRelationDTO>> listSampleGroupIds(String srcOrgId, String dstOrgId) {
        // 校验参数 + 返回指定的两个公司层级名称相同的id对
        ServiceResult<List<IdRelationDTO>> serviceResult = this.listSampleGroupLevelIds(srcOrgId, dstOrgId);
        if (!serviceResult.isSuccess()) {
            return serviceResult;
        }

        List<IdRelationDTO> levelIdRelationList = serviceResult.getData();
        // 如果层级id对集合为空,则直接返回
        if (CollectionUtils.isEmpty(levelIdRelationList)) {
            return ServiceResult.success(Collections.emptyList());
        }

        // 查询源公司组织集合
        ServiceResult<List<UserGroupDTO>> srcServiceResult = userGroupService.listByOrgId(srcOrgId);
        if (!srcServiceResult.isSuccess()) {
            ServiceResult<List<IdRelationDTO>> failResult = ServiceResult.fail(srcServiceResult.getMsg());
            failResult.setErrorCode(srcServiceResult.getErrorCode());
            return failResult;
        }

        List<UserGroupDTO> srcGroups = srcServiceResult.getData();
        if (CollectionUtils.isEmpty(srcGroups)) {
            // 源公司组织集合为空, 直接返回空集合
            return ServiceResult.success(Collections.emptyList());
        }

        // 遍历源公司公司下的所有组织: 通过目标公司id + 目标层级id + 源seq查询, 如果存在则设置为id_relations一个元素
        List<IdRelationDTO> idRelations = buildGroupIdRelations(dstOrgId, levelIdRelationList, srcGroups);
        // 遍历成功返回id_relations
        return ServiceResult.success(idRelations);
    }

    /**
     * 用户组织层级sample的拷贝
     * python引用：apps.user.tasks.copy_sample.copy_grouplevel
     * apps.user.tasks.copy_sample.copy_group
     *
     * @param srcOrgId 源租户id
     * @param dstOrgId 目标租户id
     * @return com.bestcem.xm.util.ServiceResult<java.util.Map < java.lang.String, java.lang.String>>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/01/24 14:57
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult<Map<String, String>> copySample(String srcOrgId, String dstOrgId) {
        // 参数校验
        if (!ObjectId.isValid(srcOrgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "源租户id不能为空或格式不正确");
        }
        if (!ObjectId.isValid(dstOrgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "目标租户id不能为空或格式不正确");
        }
        if (srcOrgId.equals(dstOrgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "目标租户id不能与原租户id一致");
        }
        Map<String, String> result = new HashMap<>();
        Date now = new Date();

        /*
         * 1. 拷贝租户的层级列表信息
         */
        // 查询源租户下所有的层级列表信息
        ServiceResult<List<UserGroupLevelDTO>> groupLevelResult = userGroupLevelService.listByOrgId(srcOrgId);
        if (!groupLevelResult.isSuccess() || CollectionUtils.isEmpty(groupLevelResult.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到原租户下的层级信息");
        }
        // 拷贝层级信息
        List<UserGroupLevelDTO> groupLevelList = groupLevelResult.getData().stream()
                .sorted(Comparator.comparing(UserGroupLevelDTO::getLevelNum)).collect(Collectors.toList());
        List<UserGroupLevelDTO> waitInsertList = new ArrayList<>();
        // 下级层级的Id
        String nextGroupLevelId = "";
        for (int i = 0; i < groupLevelList.size(); i++) {
            UserGroupLevelDTO userGroupLevelDTO = groupLevelList.get(i);
            UserGroupLevelDTO level = new UserGroupLevelDTO();
            level.setGroupLevelId(StringUtils.isEmpty(nextGroupLevelId) ? StringUtil.getId() : nextGroupLevelId);
            level.setGroupLevelName(userGroupLevelDTO.getGroupLevelName());
            level.setVersionId(userGroupLevelDTO.getVersionId());
            level.setLevelNum(userGroupLevelDTO.getLevelNum());
            // 设置下一层的id
            // 最后一层层级的levelChildrenId字段为null
            if (i != groupLevelList.size() - 1) {
                nextGroupLevelId = StringUtil.getId();
                level.setLevelChildrenId(nextGroupLevelId);
            }
            level.setOrgId(dstOrgId);
            level.setCreateTime(now);
            level.setUpdateTime(now);
            // 需要维护uniq_org_id_group_level_name，判断是否需要拷贝
            ServiceResult<UserGroupLevelDTO> tempGroupLevel = userGroupLevelService.getGroupByOrgIdAndName(dstOrgId, userGroupLevelDTO.getGroupLevelName());
            if (tempGroupLevel.isSuccess() && null != tempGroupLevel.getData()) {
                // 已经存在，则不插入
                result.put(userGroupLevelDTO.getGroupLevelId(), tempGroupLevel.getData().getGroupLevelId());
            } else {
                // 新增
                result.put(userGroupLevelDTO.getGroupLevelId(), level.getGroupLevelId());
                waitInsertList.add(level);
            }
        }
        userGroupLevelService.insertBatch(waitInsertList);

        /*
         * 2. 拷贝租户的组织列表信息
         * 只需要拷贝有效的和隐藏状态的即可
         */
        // 分页查询源租户的组织列表
        final Integer pageSize = 100;
        Integer currentPage = 1;
        List<Integer> statuses = Lists.newArrayList(UserGroupStatusEnum.ACTIVATED.getStatus(),
                UserGroupStatusEnum.HIDDEN.getStatus());
        GroupListRequestDto pageParam = new GroupListRequestDto();
        pageParam.setStatuses(statuses);
        pageParam.setOrgId(srcOrgId);
        ServiceResult<PageResponseDTO<UserGroupDTO>> pageDTOServiceResult = userGroupService.listPage(pageParam, pageSize, currentPage);
        Long total = 0L;
        if (pageDTOServiceResult.isSuccess()) {
            PageResponseDTO<UserGroupDTO> data = pageDTOServiceResult.getData();
            total = data.getTotal();
            List<UserGroupDTO> rows = data.getRows();
            if (CollectionUtils.isNotEmpty(rows)) {
                // 开始拷贝数据
                copyGroup(rows, dstOrgId, result);
            }
        }
        // 总页数
        int totalPage = (int) (total + total - 1) / pageSize;
        if (totalPage > 1) {
            // 开始继续分页加载
            currentPage++;
            for (; currentPage <= totalPage; currentPage++) {
                ServiceResult<List<UserGroupDTO>> byPage = userGroupService.findByPage(pageParam, pageSize, currentPage);
                if (byPage.isSuccess() && CollectionUtils.isNotEmpty(byPage.getData())) {
                    // 开始拷贝数据
                    copyGroup(byPage.getData(), dstOrgId, result);
                }
            }
        }

        /**
         * 3. copy sequence
         */
        // 3.1 拷贝组织树版本号和sequence
        String srcVersionKey = userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_LEVEL_VERSION, srcOrgId);
        String dstVersionKey = userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_LEVEL_VERSION, dstOrgId);
        String srcVersion = userCacheUtil.get(srcVersionKey);
        if (StringUtils.isNotEmpty(srcVersion)) {
            userCacheUtil.setEx(dstVersionKey, srcVersion);
        }
        SequenceDO srcVersionSequence = sequenceDao.findOneByCode(srcVersionKey);
        if (Objects.nonNull(srcVersionSequence)) {
            SequenceEntity entity = new SequenceEntity();
            entity.setSeq(srcVersionSequence.getSeq());
            entity.setUpdateTime(now);
            entity.setCreateTime(now);
            entity.setIncrStep(srcVersionSequence.getIncrStep());
            entity.setCode(dstVersionKey);
            sequenceDao.findOneAndUpdateByCode(entity);
        }

        String srcSeqKey = userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_SEQ, srcOrgId);
        String dstSeqKey = userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_SEQ, dstOrgId);
        String srcSeq = userCacheUtil.get(srcSeqKey);
        if (StringUtils.isNotEmpty(srcSeq)) {
            userCacheUtil.setEx(dstSeqKey, srcSeq);
        }
        SequenceDO srcSeqSequence = sequenceDao.findOneByCode(srcSeqKey);
        if (Objects.nonNull(srcSeqSequence)) {
            SequenceEntity entity = new SequenceEntity();
            entity.setSeq(srcSeqSequence.getSeq());
            entity.setUpdateTime(now);
            entity.setCreateTime(now);
            entity.setIncrStep(srcSeqSequence.getIncrStep());
            entity.setCode(dstSeqKey);
            sequenceDao.findOneAndUpdateByCode(entity);
        }

        return ServiceResult.success(result);
    }

    /**
     * 拷贝组织信息
     *
     * @param userGroupDTOS 组织列表
     * @param dstOrgId      目前租户id
     * @param idMaps        id映射关系
     * @return void
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/01/26 15:35
     */
    private void copyGroup(List<UserGroupDTO> userGroupDTOS, String dstOrgId, Map<String, String> idMaps) {
        if (CollectionUtils.isNotEmpty(userGroupDTOS)) {
            Date now = new Date();
            List<UserGroupDTO> userGroups = new ArrayList<>(140);
            // 批量查询目标公司是否存在了已有的组织编码对应的组织信息
            Set<String> groupCodes = userGroupDTOS.stream().map(UserGroupDTO::getGroupCode).collect(Collectors.toSet());
            ServiceResult<List<UserGroupDTO>> tempUserGroups = userGroupService.getByOrgIdAndGroupCodes(dstOrgId, groupCodes);
            Map<String, String> existsGroupCodes = new HashMap<>();
            if (tempUserGroups.isSuccess() && CollectionUtils.isNotEmpty(tempUserGroups.getData())) {
                existsGroupCodes = tempUserGroups.getData().stream().collect(Collectors.toMap(
                        UserGroupDTO::getGroupCode, UserGroupDTO::getGroupId, (t1, t2) -> t2
                ));
            }

            for (UserGroupDTO dto : userGroupDTOS) {
                // 根据orgId和groupCode判断当前组织数据是否存在
                if (existsGroupCodes.containsKey(dto.getGroupCode())) {
                    // 已经存在
                    idMaps.put(dto.getGroupId(), existsGroupCodes.get(dto.getGroupId()));
                } else {
                    // 新增
                    UserGroupDTO group = new UserGroupDTO();
                    group.setOrgId(dstOrgId);
                    group.setGroupCode(dto.getGroupCode());
                    group.setSeq(dto.getSeq());
                    group.setGroupName(dto.getGroupName());
                    group.setGroupType(dto.getGroupType());
                    group.setGroupLevelId(idMaps.get(dto.getGroupLevelId()));
                    group.setGroupStatus(dto.getGroupStatus());
                    group.setHaveChildrenFlag(dto.getHaveChildrenFlag());
                    group.setGroupOrder(dto.getGroupOrder());
                    group.setVersionId(dto.getVersionId());
                    group.setCreateTime(now);
                    group.setUpdateTime(now);
                    if (!idMaps.containsKey(dto.getGroupId())) {
                        idMaps.put(dto.getGroupId(), StringUtil.getId());
                    }
                    group.setGroupId(idMaps.get(dto.getGroupId()));
                    // 有父节点
                    if (StringUtils.isNotEmpty(dto.getGroupParentId())) {
                        if (!idMaps.containsKey(dto.getGroupParentId())) {
                            idMaps.put(dto.getGroupParentId(), StringUtil.getId());
                        }
                        group.setGroupParentId(idMaps.get(dto.getGroupParentId()));
                    } else {
                        // 没有父节点，表示为根节点
                        OrganizationDTO organizationDTO = new OrganizationDTO();
                        organizationDTO.setOrgId(dstOrgId);
                        organizationDTO.setRootGroupId(group.getGroupId());
                        organzationService.updateByPrimaryKeySelective(organizationDTO);
                    }
                    String groupParentIds = dto.getGroupParentIds();
                    if (StringUtils.isNotEmpty(groupParentIds)) {
                        // 解析为json格式
                        String parentIds = JSONUtil.toJsonStr(JSONUtil.toList(JSONUtil.parseArray(groupParentIds), String.class).stream().map(
                                g -> {
                                    if (!idMaps.containsKey(g)) {
                                        idMaps.put(g, StringUtil.getId());
                                    }
                                    return idMaps.get(g);
                                }
                        ).collect(Collectors.toList()));
                        group.setGroupParentIds(parentIds);
                    }
                    userGroups.add(group);
                }
            }
            // 批量插入
            userGroupService.insertBatch(userGroups);
        }
    }

    /**
     * 根据用户组id列表分页获取指定层级上的子用户列表
     *
     * @param groupLevelId 层级id
     * @param groupIdsList 组织id列表
     * @param currentPage  第几页
     * @param pageSize     每页大小
     * @return com.bestcem.xm.util.ServiceResult
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/01/24 15:13
     */
    @Override
    public ServiceResult<PageResponseDTO<UserGroupDTO>> pageSubRelateGroups(String groupLevelId, List<String> groupIdsList,
                                                                            Integer currentPage, Integer pageSize) {
        // 参数校验
        if (!ObjectId.isValid(groupLevelId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "层级id不能为空或格式不正确");
        }
        if (ObjectUtil.isAllEmpty(groupIdsList)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "组织id列表不能为空或格式不正确");
        }

        // 统计数量
        ServiceResult<Long> longServiceResult = userGroupService.countSubRelate(groupLevelId, groupIdsList);
        PageResponseDTO<UserGroupDTO> page = new PageResponseDTO<>();
        if (!longServiceResult.isSuccess() || longServiceResult.getData() <= 0) {
            page.setTotal(0L);
            return ServiceResult.success(page);
        }
        // 查询列表
        ServiceResult<List<UserGroupDTO>> listServiceResult = userGroupService.listPageSubRelate(groupLevelId,
                groupIdsList, pageSize, currentPage);

        page = new PageResponseDTO<>(listServiceResult.getData(), longServiceResult.getData(), currentPage);
        return ServiceResult.success(page);
    }

    /**
     * 查询当前租户组织层级是否可编辑
     *
     * @param orgId 租户Id
     * @return boolean true：已被锁定、false：未被锁定
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @date 2022/02/09 10:30
     */
    @Override
    public ServiceResult<Boolean> getLock(String orgId) {
        // 参数校验
        if (!ObjectId.isValid(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "组织Id不能为空或格式不正确");
        }
        boolean lockFlag = groupLockUtil.getLockFlag(orgId);
        return ServiceResult.success(lockFlag);
    }

    @Override
    public ServiceResult<String> updateOpenGroupTree(OpenGroupTreeParam param) {
        // 校验是否已加锁
        boolean lockFlag = groupLockUtil.getLockFlag(param.getOrgId());
        if (lockFlag) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.STATUS_CHANGED);
        }
        // 加锁
        groupLockUtil.lock(param.getOrgId());

        // 更新组织层级
        ServiceResult<String> handleResult = null;
        try {
            // 通过组织导入记录校验组织层级是否可导入
            ServiceResult<Boolean> checkImportActiveRt = userGroupImportRecordService.checkImportActive(param.getOrgId());
            if (!checkImportActiveRt.isSuccess()) {
                // 解锁
                groupLockUtil.unlock(param.getOrgId());
                return ServiceResult.fail(checkImportActiveRt.getErrorCode(), checkImportActiveRt.getMsg());
            }
            if (Boolean.FALSE.equals(checkImportActiveRt.getData())) {
                // 解锁
                groupLockUtil.unlock(param.getOrgId());
                return ServiceResult.fail(ResourceErrorCodeEnum.TASK_WORKING, "组织层级有未完成的全量更新任务，请稍后再试");
            }

            handleResult = this.updateGroupTreeByOpen(param);
        } catch (Throwable e) {
            // 解锁
            groupLockUtil.unlock(param.getOrgId());
            log.error("组织更新失败", e);
            return ServiceResult.fail("组织更新失败");
        }

        // 解锁
        groupLockUtil.unlock(param.getOrgId());
        return handleResult;
    }

    @Override
    public ServiceResult<String> updateOpenGroupTreeByAsync(OpenGroupTreeByAsyncParam param) {
        // 校验是否已加锁
        boolean lockFlag = groupLockUtil.getLockFlag(param.getOrgId());
        if (lockFlag) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.STATUS_CHANGED);
        }
        // 加锁
        groupLockUtil.lock(param.getOrgId());

        // 创建更新组织层级任务
        ServiceResult<String> handleResult = null;
        try {
            handleResult = this.handleGroupAsyncUpdate(param);
            if (!handleResult.isSuccess()
                    && !String.valueOf(ResourceErrorCodeEnum.TASK_WORKING.getCode()).equals(handleResult.getErrorCode())) {
                // 解锁
                groupLockUtil.unlock(param.getOrgId());
            }
        } catch (Throwable e) {
            groupLockUtil.unlock(param.getOrgId());
            log.error("组织异步更新失败", e);
            return ServiceResult.fail("组织异步更新失败");
        }

        return handleResult;
    }

    @Override
    public ServiceResult<List<UserGroupDTO>> getUserGroups(String userId, String orgId) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "userId is null or orgId is null");
        }

        // 查询公司信息
        ServiceResult<OrganizationDTO> organization = organzationService.selectByPrimaryKey(orgId);
        if (!organization.isSuccess() || Objects.isNull(organization.getData())) {
            return ServiceResult.fail(AuthErrorCodeEnum.ORG_NOT_EXISTS, String.format("org:%s not exists", orgId));
        }

        OrganizationDTO organizationData = organization.getData();
        String rootGroupId = organizationData.getRootGroupId();

        // 根据userId和rootGroupId查询用户所在的组列表信息
        UserUserGroupDTO param = new UserUserGroupDTO();
        param.setUserId(userId);
        param.setRootGroupId(rootGroupId);
        ServiceResult<List<String>> groupIdsResult = userUserGroupService.listGroupIdBySelective(param);
        if (!groupIdsResult.isSuccess() || CollectionUtils.isEmpty(groupIdsResult.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.OUT_OF_GROUP, "current user is out of group");
        }
        List<String> groupIds = groupIdsResult.getData();

        // 根据组织id列表查询状态为有效的组织列表
        return userGroupService.listByGroupIdsAndStatus(groupIds, UserGroupStatusEnum.ACTIVATED.getStatus());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ServiceResult<Boolean> updateOpenGroupTreeV1(OpenGroupTreeParam param) {
        String orgId = param.getOrgId();
        // 查询出老的所有层级
        ServiceResult<List<UserGroupLevelDTO>> oldLevelResult = userGroupLevelService.listByOrgId(param.getOrgId());
        List<UserGroupLevelDTO> oldLevelList = oldLevelResult.getData();

        // 老的所有层级 name-levelNum 映射
        Map<String, Integer> oldLevelMap = new HashMap<>();
        for (UserGroupLevelDTO userGroupLevelDTO : oldLevelList) {
            oldLevelMap.put(userGroupLevelDTO.getGroupLevelName(), userGroupLevelDTO.getLevelNum());
        }

        // 新版所有层级 name-levelNum 映射
        Map<String, Integer> newLevelMap = new HashMap<>();
        for (GroupLevelSyncParam syncParam : param.getLevels()) {
            newLevelMap.put(syncParam.getName(), syncParam.getLevel());
        }

        // 老的层级名称列表 用于区分层级的增删改
        List<String> oldLevelNameList = oldLevelList.stream().map(UserGroupLevelDTO::getGroupLevelName).collect(Collectors.toList());

        for (GroupLevelSyncParam level : param.getLevels()) {
            // 需要新增的层级
            if (!oldLevelNameList.contains(level.getName())) {
                UserGroupLevelDTO userGroupLevelDTO = new UserGroupLevelDTO();
                userGroupLevelDTO.setOrgId(orgId);
                userGroupLevelDTO.setGroupLevelName(level.getName());
                userGroupLevelDTO.setLevelNum(level.getLevel());
                // python的model类型默认的{}
                userGroupLevelDTO.setLevelDisplay("{}");
                ServiceResult<String> levelResult = userGroupLevelService.insert(userGroupLevelDTO);
                String levelId = levelResult.getData();
                // 由于在dao层进行了数据转换，userGroupLevelDTO没有levelId 需要重新赋值
                userGroupLevelDTO.setGroupLevelId(levelId);

            }
        }

        // 新的层级名称列表
        List<String> newLevelNameList = param.getLevels().stream().map(GroupLevelSyncParam::getName).collect(Collectors.toList());
        // 需要删除的层级
        List<String> deleteLevelNameList = new ArrayList<>();
        for (String oldLevelName : oldLevelNameList) {
            // 新版的层级列表不包含oldLevelName 则需要删除
            if (!newLevelNameList.contains(oldLevelName)) {
                deleteLevelNameList.add(oldLevelName);
            }

            // 新版的层级列表包含oldLevelName 但层级数不同 则需要删除
            if (newLevelNameList.contains(oldLevelName) && !newLevelMap.get(oldLevelName).equals(oldLevelMap.get(oldLevelName))) {
                deleteLevelNameList.add(oldLevelName);
            }
        }
        // 需要删除的层级id列表
        List<String> levelIdList = oldLevelList.stream().filter(s -> deleteLevelNameList.contains(s.getGroupLevelName())).map(UserGroupLevelDTO::getGroupLevelId).collect(Collectors.toList());
        // 批量删除层级
        userGroupLevelService.deleteByIds(levelIdList);

        // 当前的层级结构 从小到大排序
        ServiceResult<List<UserGroupLevelDTO>> groupLevelResult = userGroupLevelService.listByOrgId(orgId);
        List<UserGroupLevelDTO> groupLevelList = groupLevelResult.getData().stream().sorted(Comparator.comparing(UserGroupLevelDTO::getLevelNum))
                .collect(Collectors.toList());

        // 给层级重新设置levelChildrenId
        for (int i = 0; i < groupLevelList.size(); i++) {
            UserGroupLevelDTO userGroupLevelDTO = groupLevelList.get(i);
            if (i != (groupLevelList.size() - 1)) {
                // 末级层级不更新childLevelId
                UserGroupLevelDTO nextLevel = groupLevelList.get(i + 1);
                userGroupLevelDTO.setLevelChildrenId(nextLevel.getGroupLevelId());
            } else {
                // 末级层级childLevelId置为null
                userGroupLevelDTO.setLevelChildrenId(null);
            }
            userGroupLevelService.updateLevel(userGroupLevelDTO);
        }

        // ========= 处理组织 =======================

        ServiceResult<OrganizationDTO> orgRst = organzationService.selectByPrimaryKey(orgId);
        OrganizationDTO organizationDTO = orgRst.getData();


        // 新版的组织
        Set<String> newGroupCodeSet = param.getGroups().stream().map(GroupSyncParam::getCode).collect(Collectors.toSet());

        List<UserGroupDTO> userGroupDTOList = userGroupService.listByOrgIdAndStatuses(orgId);
        // 旧版组织code-group映射
        Map<String, UserGroupDTO> oldGroupCodeMap = new HashMap<>();
        // 旧版组织groupCode集合
        Set<String> oldGroupCodeSet = new HashSet<>();
        for (UserGroupDTO userGroupDTO : userGroupDTOList) {
            oldGroupCodeMap.put(userGroupDTO.getGroupCode(), userGroupDTO);
            oldGroupCodeSet.add(userGroupDTO.getGroupCode());
        }

        // 需要添加的groupCode
        Set<String> insertGroupCodeSet = new HashSet<>(newGroupCodeSet);
        insertGroupCodeSet.removeAll(oldGroupCodeSet);

        // 需要失效的groupCode
        Set<String> deleteGroupCodeSet = new HashSet<>(oldGroupCodeSet);
        deleteGroupCodeSet.removeAll(newGroupCodeSet);

        // 新版组织code-group映射(更新插入已此为准) 需要持续更新最新的group数据
        Map<String, UserGroupDTO> newGroupCodeMap = new HashMap<>();
        // 组织名称发生变化的组织信息
        List<GroupNameInfo> groupNameInfos = new ArrayList<>();
        for (GroupSyncParam syncParam : param.getGroups()) {
            UserGroupDTO oldGroup = oldGroupCodeMap.get(syncParam.getCode());
            UserGroupDTO groupDTO = new UserGroupDTO();
            groupDTO.setGroupCode(syncParam.getCode());
            groupDTO.setAdminName(syncParam.getAdminName());
            groupDTO.setAdminId(getUserIdByOrgIdAndUserName(orgId, syncParam.getAdminName()));
            groupDTO.setGroupName(syncParam.getName());
            groupDTO.setOrgId(orgId);
            // 一次性取完所有seq   不管新老节点都重新设置seq,
            // 因为可能根节点变成某个子节点，但是rootGroupId不变，
            // 在更新这个根节点内容时，因为有org_id和seq的唯一索引存在，导致更新失败
            groupDTO.setSeq(sequenceService.incrementVersion(userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_SEQ, orgId)));
            if (Objects.nonNull(oldGroup)) {
                groupDTO.setGroupId(oldGroup.getGroupId());
                groupDTO.setGroupParentId(oldGroup.getGroupParentId());
                groupDTO.setVersionId(oldGroup.getVersionId());
                groupDTO.setUpdateTime(new Date());
                // 组织名称发生变化，需要记录并通知投放
                if (!groupDTO.getGroupName().equals(oldGroup.getGroupName())) {
                    GroupNameInfo groupNameInfo = new GroupNameInfo();
                    groupNameInfo.setGroupId(oldGroup.getGroupId());
                    groupNameInfo.setOldGroupName(oldGroup.getGroupName());
                    groupNameInfo.setNewGroupName(groupDTO.getGroupName());
                    groupNameInfos.add(groupNameInfo);
                }
            } else {
                groupDTO.setCreateTime(new Date());
            }
            groupDTO.setGroupStatus(UserGroupStatusEnum.ACTIVATED.getStatus());
            newGroupCodeMap.put(syncParam.getCode(), groupDTO);
        }

        // 同一个groupCode进行分组
        Map<String, List<GroupSyncParam>> groupMap = param.getGroups().stream().collect(Collectors.groupingBy(GroupSyncParam::getParentCode));

        // 设置父组织的code和层级id映射关系,方便给组织分别设置层级id
        Map<String, String> parentCodeToLevelIdMap = new HashMap<>();
        if (CollectionUtils.isEmpty(groupMap.get(StringUtils.EMPTY))) {
            throw new GrpcCallFailedException("根节点缺失");
        }
        if (groupMap.get(StringUtils.EMPTY).size() != 1) {
            throw new GrpcCallFailedException("不允许存在多个根节点");
        }
        // 根节点
        GroupSyncParam rootParam = groupMap.get(StringUtils.EMPTY).get(0);
        // 根节点对应的层级
        String levelId = groupLevelList.get(0).getGroupLevelId();
        // 根节点的parentCode对应的层级id
        parentCodeToLevelIdMap.put(rootParam.getParentCode(), levelId);
        //
        ServiceResult<UserGroupLevelDTO> levelResult = userGroupLevelService.getById(levelId);
        UserGroupLevelDTO groupLevelDTO = levelResult.getData();
        // 下一个节点对应的parentCode
        String nextParentCode = rootParam.getCode();
        setParentCodeToLevelId(nextParentCode, groupLevelDTO.getLevelChildrenId(), parentCodeToLevelIdMap, groupMap);

        // 设置根节点参数
        GroupSyncParam rootGroupParam = groupMap.get(StringUtils.EMPTY).get(0);
        ServiceResult<UserGroupDTO> rootGroupResult = userGroupService.getRootGroupByOrgId(orgId);
        UserGroupDTO rootGroup = rootGroupResult.getData();
        String parentCode = rootGroupParam.getCode();
        String rootGroupId = "";
        if (Objects.nonNull(rootGroup)) {
            // 之前存在根组织
            rootGroup.setGroupCode(rootGroupParam.getCode());
            rootGroup.setAdminName(rootGroupParam.getAdminName());
            rootGroup.setAdminId(getUserIdByOrgIdAndUserName(orgId, rootGroupParam.getAdminName()));
            rootGroup.setGroupName(rootGroupParam.getName());
            rootGroup.setHaveChildrenFlag(BooleanStatusEnum.YES.getStatus());
            rootGroup.setGroupLevelId(groupLevelList.get(0).getGroupLevelId());
            Integer version = rootGroup.getVersionId();
            rootGroup.setVersionId(rootGroup.getVersionId() + 1);
            userGroupService.updateByIdAndVersion(version, rootGroup);
            rootGroupId = rootGroup.getGroupId();
            // 更新根组织在newGroupCodeMap的数据
            newGroupCodeMap.put(rootGroupParam.getCode(), rootGroup);

        } else {
            // 不存在根组织 需要新增
            UserGroupDTO newRootGroup = new UserGroupDTO();
            newRootGroup.setOrgId(orgId);
            newRootGroup.setGroupCode(rootGroupParam.getCode());
            newRootGroup.setAdminName(rootGroupParam.getAdminName());
            newRootGroup.setAdminId(getUserIdByOrgIdAndUserName(orgId, rootGroupParam.getAdminName()));
            newRootGroup.setGroupName(rootGroupParam.getName());
            newRootGroup.setHaveChildrenFlag(BooleanStatusEnum.YES.getStatus());
            newRootGroup.setSeq(sequenceService.incrementVersion(userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_SEQ, orgId)));
            newRootGroup.setGroupType(UserGroupTypeEnum.DEFAULT.getCode());
            newRootGroup.setGroupStatus(UserGroupStatusEnum.ACTIVATED.getStatus());
            newRootGroup.setGroupLevelId(groupLevelList.get(0).getGroupLevelId());
            newRootGroup.setGroupOrder(NumberUtils.INTEGER_ZERO);
            newRootGroup.setVersionId(UserGroupConstant.INITIAL_VERSION);
            newRootGroup.setGroupParentIds("[]");
            ServiceResult<String> result = userGroupService.insertSelect(newRootGroup);
            rootGroupId = result.getData();
            // 更新组织在newGroupCodeMap的数据
            newGroupCodeMap.put(rootGroupParam.getCode(), newRootGroup);
        }

        if (StringUtils.isNotBlank(organizationDTO.getRootGroupId())) {
            rootGroupId = organizationDTO.getRootGroupId();
        } else {
            organizationDTO.setRootGroupId(rootGroupId);
            organzationService.updateByPrimaryKeySelective(organizationDTO);
        }

        // 需要删除的groupId
        List<String> deleteIdList = new ArrayList<>();
        for (String deleteGroupCode : deleteGroupCodeSet) {
            if (oldGroupCodeMap.containsKey(deleteGroupCode)) {
                // 根组不应该被删除或失效，应该是进行更新
                UserGroupDTO delGroup = oldGroupCodeMap.get(deleteGroupCode);
                if (delGroup.getGroupId().equals(rootGroupId)) {
                    continue;
                }
                deleteIdList.add(delGroup.getGroupId());
            }
        }

        // 递归设置并添加子组织 除了根节点 其他组织都在这里添加
        subGroupHand(groupMap.get(parentCode), parentCode, groupMap, newGroupCodeMap, parentCodeToLevelIdMap);

        // 更新组织树的版本号
        groupSequenceUtil.incrementVersion(orgId);

        // 组织名称变更发送消息
        userMessageSendService.publishGroupTitleModifyList(orgId, groupNameInfos);

        // 添加新增节点
        List<StoreInfo> storeInfoList = new ArrayList<>();
        for (String insertGroupCode : insertGroupCodeSet) {
            UserGroupDTO newGroup = newGroupCodeMap.get(insertGroupCode);
            // 门店新增才需要发送消息
            if ((NumberUtils.INTEGER_ZERO.equals(newGroup.getHaveChildrenFlag()))) {
                StoreInfo storeInfo = new StoreInfo();
                storeInfo.setGroupId(newGroup.getGroupId());
                storeInfo.setGroupName(newGroup.getGroupName());
                storeInfo.setGroupCode(newGroup.getGroupCode());
                storeInfoList.add(storeInfo);
            }
        }
        // 批量新增门店发送消息
        userMessageSendService.publishCreateStoreList(orgId, rootGroupId, storeInfoList);

        // 发送消息: 组织发生变化
        userMessageSendService.publishGroupsChange(orgId, rootGroupId);

        if (CollectionUtils.isNotEmpty(deleteIdList)) {
            deleteGroup(deleteIdList);
        }

        // 需要删除的层级
        for (String deleteId : levelIdList) {
            userMessageSendService.publishGroupLevelDelete(orgId, deleteId);
        }

        // 需要删除的组织 (删除也发送失效的消息，python统一处理)
        userMessageSendService.publishGroupInvalidateList(orgId, deleteIdList);

        return ServiceResult.success(Boolean.TRUE);
    }

    private Integer deleteGroup(List<String> groupIdList) {
        for (String groupId : groupIdList) {
            ServiceResult<UserGroupDTO> userGroupRst = userGroupService.getById(groupId);
            UserGroupDTO userGroupDTO = userGroupRst.getData();
            UserGroupDTO check = new UserGroupDTO();
            check.setGroupParentId(userGroupDTO.getGroupId());
            ServiceResult<List<UserGroupDTO>> childrenGroupRst = userGroupService.listByCondition(check);
            List<UserGroupDTO> childGroupList = childrenGroupRst.getData();
            if (CollectionUtils.isNotEmpty(childGroupList)) {
                for (UserGroupDTO groupDTO : childGroupList) {
                    groupDTO.setGroupParentId(groupDTO.getGroupParentId());
                    groupDTO.setGroupParentIds(groupDTO.getGroupParentIds());
                    userGroupService.updateByIdAndVersion(groupDTO.getVersionId(), groupDTO);
                }
            }
            userGroupService.updateStatusById(groupId, UserGroupStatusEnum.DELETED.getStatus());
        }
        return groupIdList.size();
    }

    /**
     * 递归设置父组织与层级id
     * 分组的设计 同一组的levelId是相同的
     *
     * @param parentCode             下一级父组织code
     * @param levelId                下一级层级id
     * @param parentCodeToLevelIdMap 父组织code和levelId映射关系
     * @param groupMap               以parentCode进行分组 parentCode-子组织列表
     * @return void
     * @author Linzhijian <zhijian.lin@idiaoyan.com>
     * @date 2022/07/15 19:48
     */
    private void setParentCodeToLevelId(String parentCode, String levelId, Map<String, String> parentCodeToLevelIdMap, Map<String, List<GroupSyncParam>> groupMap) {
        ServiceResult<UserGroupLevelDTO> levelResult = userGroupLevelService.getById(levelId);
        UserGroupLevelDTO groupLevelDTO = levelResult.getData();
        parentCodeToLevelIdMap.put(parentCode, groupLevelDTO.getGroupLevelId());
        List<GroupSyncParam> groupSyncParams = groupMap.get(parentCode);
        if (CollectionUtils.isNotEmpty(groupSyncParams) && StringUtils.isNotBlank(groupLevelDTO.getLevelChildrenId())) {
            for (GroupSyncParam groupSyncParam : groupSyncParams) {
                String groupLevelId = groupLevelDTO.getLevelChildrenId();
                setParentCodeToLevelId(groupSyncParam.getCode(), groupLevelId, parentCodeToLevelIdMap, groupMap);
            }
        }
    }

    /**
     * 递归设置并添加子组织
     * 除了根节点 其他组织都在这里添加
     *
     * @param paramList              同一个父组织的集合
     * @param parentCode             父组织的code
     * @param groupMap               同一个groupCode进行分组
     * @param newGroupCodeMap        新版的集合映射
     * @param parentCodeToLevelIdMap
     * @return void
     * @author Linzhijian <zhijian.lin@idiaoyan.com>
     * @date 2022/07/15 00:05
     */
    private void subGroupHand(List<GroupSyncParam> paramList, String parentCode, Map<String, List<GroupSyncParam>> groupMap, Map<String, UserGroupDTO> newGroupCodeMap, Map<String, String> parentCodeToLevelIdMap) {
        if (CollectionUtils.isNotEmpty(paramList)) {
            for (GroupSyncParam groupSyncParam : paramList) {
                UserGroupDTO userGroupDTO = newGroupCodeMap.get(groupSyncParam.getCode());
                UserGroupDTO parentGroup = newGroupCodeMap.get(parentCode);
                JSONArray groupParentIdArray = JSON.parseArray(parentGroup.getGroupParentIds());
                if (Objects.nonNull(groupParentIdArray) && CollectionUtils.isNotEmpty(groupParentIdArray)) {
                    groupParentIdArray.add(parentGroup.getGroupId());
                } else {
                    groupParentIdArray = new JSONArray();
                    groupParentIdArray.add(parentGroup.getGroupId());
                }
                userGroupDTO.setSeq(sequenceService.incrementVersion(userCacheUtil.buildKey(UserCacheKeyConstant.USER_GROUP_SEQ, userGroupDTO.getOrgId())));
                if (StringUtils.isBlank(parentCodeToLevelIdMap.get(parentCode))) {
                    throw new GrpcCallFailedException("层级缺失");
                }
                userGroupDTO.setGroupLevelId(parentCodeToLevelIdMap.get(parentCode));
                userGroupDTO.setGroupParentId(parentGroup.getGroupId());
                userGroupDTO.setGroupParentIds(JSON.toJSONString(groupParentIdArray));
                userGroupDTO.setGroupOrder(userGroupService.getMaxChildrenOrderByGroupId(parentGroup.getGroupId()));
                userGroupDTO.setHaveChildrenFlag(CollectionUtils.isNotEmpty(groupMap.get(groupSyncParam.getCode())) ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO);
                // 需要新增
                if (StringUtils.isBlank(userGroupDTO.getGroupId())) {
                    userGroupService.insertSelect(userGroupDTO);
                } else {
                    userGroupService.updateByIdAndVersion(userGroupDTO.getVersionId(), userGroupDTO);
                }
                // 更新最新的group数据
                newGroupCodeMap.put(groupSyncParam.getCode(), userGroupDTO);
                subGroupHand(groupMap.get(groupSyncParam.getCode()), userGroupDTO.getGroupCode(), groupMap, newGroupCodeMap, parentCodeToLevelIdMap);
            }
        }
    }

    private String getUserIdByOrgIdAndUserName(String orgId, String userName) {
        if (StringUtils.isNotBlank(userName)) {
            UserDTO check = new UserDTO();
            check.setOrgId(orgId);
            check.setUserName(userName);
            ServiceResult<List<UserDTO>> result = userService.listByCondition(check);
            if (CollectionUtils.isNotEmpty(result.getData())) {
                return result.getData().get(0).getUserId();
            }
        }
        return "";
    }

    /**
     * 开放平台更新组织层级
     *
     * @param param 更新组织层级参数
     * @return ServiceResult<String>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/21 10:19
     */
    private ServiceResult<String> updateGroupTreeByOpen(OpenGroupTreeParam param) {
        // 校验参数
        ServiceResult<String> checkResult = updateOpenGroupTreeCheck(param);
        if (!checkResult.isSuccess()) {
            return checkResult;
        }
        // 设置组负责人账号id
        ServiceResult<Map<String, String>> groupAdminRt = this.checkAndGetGroupAdmin(param);
        if (!groupAdminRt.isSuccess()) {
            if (groupAdminRt.getData() != null && groupAdminRt.getData().size() > 0) {
                return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_ADMIN_NOT_FOUND, new ArrayList<>(groupAdminRt.getData().keySet()).get(0));
            }
            return ServiceResult.fail(null, groupAdminRt.getMsg(), groupAdminRt.getErrorCode());
        }
        Map<String, String> usernameAndIdMap = groupAdminRt.getData();

        // 设置参数
        // 设置token参数
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setOrgId(param.getOrgId());

        // 设置层级参数
        Map<Integer, String> levelNames = new HashMap<>();
        Map<String, Integer> levelMap = new LinkedHashMap<>();
        List<GroupLevelSyncParam> sortedLevel = param.getLevels().stream()
                .sorted(Comparator.comparing(GroupLevelSyncParam::getLevel)).collect(Collectors.toList());
        int levelNum = UserGroupConstant.LEVEL_NUM_BEGIN;
        for (GroupLevelSyncParam level : sortedLevel) {
            levelNames.put(levelNum, level.getName());
            levelMap.put(level.getName(), levelNum);
            levelNum++;
        }

        // 设置组织参数
        List<UserGroupImportDTO> importDTOS = new ArrayList<>();
        Map<String, List<GroupSyncParam>> groupMap = param.getGroups().stream().collect(Collectors.groupingBy(GroupSyncParam::getParentCode));

        // 设置根节点参数
        GroupSyncParam rootGroupParam = groupMap.get(StringUtils.EMPTY).get(0);
        UserGroupImportDTO rootGroup = UserGroupImportDTO.builder()
                .groupCode(rootGroupParam.getCode())
                .groupName(rootGroupParam.getName())
                .fullGroupName(rootGroupParam.getName())
                .parentFullGroupName(StringUtils.EMPTY)
                .groupLevelName(rootGroupParam.getLevelName())
                .groupStatus(UserGroupStatusEnum.ACTIVATED.getStatus())
                .haveChildrenFlag(HaveChildrenFlagEnum.NOT_HAVE.getStatus())
                .adminId(this.getUserIdByUsername(usernameAndIdMap, rootGroupParam.getAdminName()))
                .build();
        importDTOS.add(rootGroup);

        // 设置父组织名称集合
        List<String> fullParentGroupNames = new ArrayList<>();
        Set<String> fullGroupNameSet = new HashSet<>();
        fullGroupNameSet.add(rootGroup.getGroupName());
        fullParentGroupNames.add(rootGroup.getGroupName());
        // 递归设置子组织参数
        handleGroupData(importDTOS, rootGroup, groupMap, fullParentGroupNames, fullGroupNameSet, levelMap, usernameAndIdMap);

        // 保存层级组织
        ServiceResult<String> saveResult = groupImportHandler.saveGroupTree(levelNames, importDTOS, tokenDTO);
        if (!saveResult.isSuccess()) {
            return ServiceResult.fail("层级同步失败");
        }

        return ServiceResult.success();
    }

    /**
     * 通过组负责人账号名查询组负责人账号id, 并进行校验
     *
     * @param param
     * @return ServiceResult<Map < String>>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/8/2 11:34
     */
    private ServiceResult<Map<String, String>> checkAndGetGroupAdmin(OpenGroupTreeParam param) {
        // 设置查询参数
        Set<String> adminNames = param.getGroups().stream()
                .filter(item -> StringUtils.isNotBlank(item.getAdminName()))
                .map(GroupSyncParam::getAdminName).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(adminNames)) {
            return ServiceResult.success();
        }
        // 查询并返回
        return userService.listIdsByUserName(adminNames, param.getOrgId());
    }

    /**
     * 通过账号名获取用户----------
     *
     * @param usernameAndIdMap
     * @param username
     * @return String
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/7/13 18:32
     */
    private String getUserIdByUsername(Map<String, String> usernameAndIdMap, String username) {
        return usernameAndIdMap != null && StringUtils.isNotBlank(username) ? usernameAndIdMap.get(username) : StringUtils.EMPTY;
    }

    /**
     * 开放平台异步更新组织层级
     *
     * @param param 更新组织层级参数
     * @return ServiceResult<String>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/21 10:19
     */
    private ServiceResult<String> handleGroupAsyncUpdate(OpenGroupTreeByAsyncParam param) {
        // 校验参数
        ServiceResult<Object> checkResult = ValidatorUtil.validateFast(param);
        if (!checkResult.isSuccess()) {
            ServiceResult<String> result = ServiceResult.fail(checkResult.getMsg());
            result.setErrorCode(checkResult.getErrorCode());
            return result;
        }

        // 通过组织导入记录校验组织层级是否可导入
        ServiceResult<Boolean> checkImportActiveRt = userGroupImportRecordService.checkImportActive(param.getOrgId());
        if (!checkImportActiveRt.isSuccess()) {
            return ServiceResult.fail(checkImportActiveRt.getErrorCode(), checkImportActiveRt.getMsg());
        }
        if (Boolean.FALSE.equals(checkImportActiveRt.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.TASK_WORKING, "组织层级有未完成的全量更新任务，请稍后再试");
        }

        // 保存待处理的组织导入记录
        UserGroupImportRecordDTO importRecordDTO = new UserGroupImportRecordDTO();
        importRecordDTO.setOrgId(param.getOrgId());
        importRecordDTO.setStatus(GroupImportRecordStatusEnum.ON_HAND.getStatus());
        importRecordDTO.setType(GroupImportRecordTypeEnum.OPEN_PLATFORM.getType());
        importRecordDTO.setImportFilePath(param.getGroupFilePath());
        importRecordDTO.setContent(param.getCallbackParam());
        String importId = userGroupImportRecordService.insert(importRecordDTO).getData();
        importRecordDTO.setImportId(importId);

        // 向线程池提交任务
        this.getThreadPoolExecutor(param.getGroupTotal()).execute(() -> updateGroupByOpenImportRecord(importRecordDTO));

        return ServiceResult.success(importId);
    }


    /**
     * 通过开放平台的组织导入记录更新组织层级
     *
     * @param importRecordDTO 导入组织记录对象
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/20 14:34
     */
    private void updateGroupByOpenImportRecord(UserGroupImportRecordDTO importRecordDTO) {
        // 正在处理，更新状态为处理中
        userGroupImportRecordService.updateStatus(importRecordDTO.getOrgId(), importRecordDTO.getImportId(), GroupImportRecordStatusEnum.HANDING.getStatus());
        try {
            // 设置参数
            // 读取excel文件数据,校验文件内容格式, 保存组织层级
            ServiceResult<String> result = this.process(importRecordDTO);
            if (result.isSuccess()) {
                // 处理成功，更新状态为处理成功
                importRecordDTO.setStatus(GroupImportRecordStatusEnum.SUCCESS_HAND.getStatus());
                userGroupImportRecordService.updateStatus(importRecordDTO.getOrgId(), importRecordDTO.getImportId(), importRecordDTO.getStatus());
            } else {
                // 处理失败，更新状态为处理失败
                importRecordDTO.setStatus(GroupImportRecordStatusEnum.FAIL_HAND.getStatus());
                importRecordDTO.setErrorMsg(result.getMsg());

                UserGroupImportRecordDTO updateImportRecord = new UserGroupImportRecordDTO();
                updateImportRecord.setStatus(importRecordDTO.getStatus());
                updateImportRecord.setErrorMsg(importRecordDTO.getErrorMsg());
                updateImportRecord.setOrgId(importRecordDTO.getOrgId());
                updateImportRecord.setImportId(importRecordDTO.getImportId());
                if (StringUtils.isNotBlank(result.getData())) {
                    updateImportRecord.setErrorFilePath(result.getData());
                }
                userGroupImportRecordService.updateByIdAndOrgId(updateImportRecord);
            }

            // 发送mq: 开放平台异步更新组织层级完成
            //userGroupMessageSender.publishOpenGroupUpdateFinish(importRecordDTO.getOrgId(), importRecordDTO.getImportId(),
            //        importRecordDTO.getContent(), importRecordDTO.getStatus(), importRecordDTO.getErrorMsg());

        } catch (Throwable e) {
            log.error("导入组织层级失败", e);
            // 处理失败，更新状态为处理失败
            UserGroupImportRecordDTO updateImportRecord = new UserGroupImportRecordDTO();
            updateImportRecord.setStatus(GroupImportRecordStatusEnum.FAIL_HAND.getStatus());
            updateImportRecord.setErrorMsg("未知异常, 导入组织层级失败");
            updateImportRecord.setOrgId(importRecordDTO.getOrgId());
            updateImportRecord.setImportId(importRecordDTO.getImportId());
            userGroupImportRecordService.updateByIdAndOrgId(updateImportRecord);
        }

        // 解锁
        groupLockUtil.unlock(importRecordDTO.getOrgId());
    }

    /**
     * 更新组织层级
     *
     * @param importRecordDTO 组织导入记录
     * @return ServiceResult<String>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/21 13:50
     */
    private ServiceResult<String> process(UserGroupImportRecordDTO importRecordDTO) {
        // 读取excel文件并设置参数
        ServiceResult<OpenGroupTreeParam> paramResult = readFileToEntity(importRecordDTO);
        if (!paramResult.isSuccess()) {
            return ServiceResult.fail(paramResult.getMsg());
        }

        return this.updateGroupTreeByOpen(paramResult.getData());
    }

    /**
     * 读取excel文件并设置参数
     *
     * @param importRecordDTO 组织导入记录
     * @return ServiceResult<OpenGroupTreeParam>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/21 14:49
     */
    private ServiceResult<OpenGroupTreeParam> readFileToEntity(UserGroupImportRecordDTO importRecordDTO) {
        // 下载文件
        //InputStream inputStream = ossService.downloadFile(importRecordDTO.getImportFilePath());
        InputStream inputStream = new ByteArrayInputStream(storageService.downloadByUrl(storageService.getPropertiesValueBy(null, "domain") + importRecordDTO.getImportFilePath()).bytes());

        // 读取excel文件
        // 读取层级sheet
        ExcelReader excelReader = EasyExcelFactory.read(inputStream).build();
        OpenLevelReadListener levelReadListener = new OpenLevelReadListener();
        ReadSheet levelSheet = EasyExcelFactory.readSheet("group_levels").head(GroupLevelSyncParam.class)
                .registerReadListener(levelReadListener)
                .build();
        excelReader.read(levelSheet);
        if (levelReadListener.hasDataError() || levelReadListener.hasReadError()) {
            return ServiceResult.fail(levelReadListener.getErrorMsg());
        }

        // 读取组织sheet
        OpenGroupReadListener groupReadListener = new OpenGroupReadListener();
        ReadSheet groupSheet = EasyExcelFactory.readSheet("groups").head(GroupSyncParam.class)
                .registerReadListener(groupReadListener)
                .build();
        excelReader.read(groupSheet);
        if (groupReadListener.hasDataError() || groupReadListener.hasReadError()) {
            return ServiceResult.fail(groupReadListener.getErrorMsg());
        }

        // 设置返回值
        OpenGroupTreeParam param = new OpenGroupTreeParam();
        param.setOrgId(importRecordDTO.getOrgId());
        param.setLevels(levelReadListener.getDataList());
        param.setGroups(groupReadListener.getDataList());
        return ServiceResult.success(param);
    }

    /**
     * 通过文件大小获取对应的线程池
     *
     * @param groupSize 组织数量
     * @return ThreadPoolExecutor
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/20 14:31
     */
    private ThreadPoolExecutor getThreadPoolExecutor(int groupSize) {
        if (groupSize < 10000) {
            return AsyncUtil.LITTLE_GROUP_THREAD_POOL_EXECUTOR;
        } else {
            return AsyncUtil.MUCH_GROUP_THREAD_POOL_EXECUTOR;
        }
    }

    /**
     * 设置参数-开放平台的层级更新
     *
     * @param importDTOS               导入组织集合
     * @param parentGroup              父组织
     * @param groupMap                 组织集合
     * @param lastFullParentGroupNames 父组织的名称全路径集合
     * @param fullGroupNameSet         已处理组织的名称全路径集合
     * @param levelMap                 层级集合
     */
    private void handleGroupData(List<UserGroupImportDTO> importDTOS, UserGroupImportDTO parentGroup, Map<String, List<GroupSyncParam>> groupMap,
                                 List<String> lastFullParentGroupNames, Set<String> fullGroupNameSet,
                                 Map<String, Integer> levelMap, Map<String, String> usernameAndIdMap) {

        // 递归设置其他节点参数
        List<GroupSyncParam> groupSyncParams = groupMap.get(parentGroup.getGroupCode());
        if (CollectionUtils.isEmpty(groupSyncParams)) {
            return;
        }
        parentGroup.setHaveChildrenFlag(HaveChildrenFlagEnum.HAVE.getStatus());

        for (GroupSyncParam groupSyncParam : groupSyncParams) {
            // 子节点层级数
            Integer childLevelNum = levelMap.get(groupSyncParam.getLevelName());
            // 父节点层级数
            Integer parentLevelNum = levelMap.get(groupSyncParam.getParentLevelName());

            List<String> fullParentGroupNames = JSON.parseArray(JSON.toJSONString(lastFullParentGroupNames), String.class);

            // 从上层往下层添加组织
            for (Map.Entry<String, Integer> entry : levelMap.entrySet()) {
                Integer levelNum = entry.getValue();
                // 如果当前层级大于父层级, 则继续往下找
                if (levelNum <= parentLevelNum) {
                    continue;
                }
                // 如果当前层级小于子层级, 则直接退出
                if (levelNum > childLevelNum) {
                    break;
                }

                UserGroupImportDTO chileGroup = UserGroupImportDTO.builder().build();
                chileGroup.setGroupCode(groupSyncParam.getCode());
                chileGroup.setGroupName(groupSyncParam.getName());
                chileGroup.setGroupStatus(UserGroupStatusEnum.ACTIVATED.getStatus());
                chileGroup.setGroupLevelName(entry.getKey());
                chileGroup.setHaveChildrenFlag(HaveChildrenFlagEnum.NOT_HAVE.getStatus());

                // 添加隐藏节点
                if (!childLevelNum.equals(levelNum)) {
                    chileGroup.setGroupCode(StringUtils.EMPTY);
                    chileGroup.setGroupName(parentGroup.getGroupName());
                    chileGroup.setGroupStatus(UserGroupStatusEnum.HIDDEN.getStatus());
                    chileGroup.setGroupLevelName(entry.getKey());
                    chileGroup.setHaveChildrenFlag(HaveChildrenFlagEnum.HAVE.getStatus());
                }

                String parentFullGroupName = StringUtils.join(fullParentGroupNames, ",");
                List<String> fullGroupNames = JSON.parseArray(JSON.toJSONString(fullParentGroupNames), String.class);
                fullGroupNames.add(chileGroup.getGroupName());
                String fullGroupName = StringUtils.join(fullGroupNames, ",");
                // 设置父节点路径
                fullParentGroupNames = JSON.parseArray(JSON.toJSONString(fullGroupNames), String.class);

                // 判断是否已经有该节点(用于去除重复的隐藏节点)
                if (fullGroupNameSet.contains(fullGroupName)) {
                    continue;
                }
                fullGroupNameSet.add(fullGroupName);

                // 设置组织参数
                // 判断是否是有效组织, 有效组织设置组织负责人, 隐藏节点不设置组织负责人
                if (UserGroupStatusEnum.ACTIVATED.getStatus().equals(chileGroup.getGroupStatus())) {
                    chileGroup.setAdminId(this.getUserIdByUsername(usernameAndIdMap, groupSyncParam.getAdminName()));
                }

                chileGroup.setFullGroupName(fullGroupName);
                chileGroup.setParentFullGroupName(parentFullGroupName);

                importDTOS.add(chileGroup);

                // 如果是活动的组织,则设置其子组织信息
                if (UserGroupStatusEnum.ACTIVATED.getStatus().equals(chileGroup.getGroupStatus())) {
                    handleGroupData(importDTOS, chileGroup, groupMap, fullParentGroupNames, fullGroupNameSet, levelMap, usernameAndIdMap);
                }
            }
        }
    }

    /**
     * 比较目标公司层级和源公司层级的名称
     *
     * @param srcLevels 原公司层级信息列表
     * @param dstLevels 目标公司层级信息列表
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/1/21 11:30
     */
    private List<IdRelationDTO> buildLevelIdRelations(List<UserGroupLevelDTO> srcLevels, List<UserGroupLevelDTO> dstLevels) {
        // 设置返回值
        List<IdRelationDTO> idRelations = new ArrayList<>();
        // 源公司层级集合过滤处理
        Map<String, UserGroupLevelDTO> groupLevelMap = srcLevels.stream()
                .filter(v -> StringUtils.isNotBlank(v.getGroupLevelName()))
                .collect(Collectors.toMap(UserGroupLevelDTO::getGroupLevelName, item -> item));

        // 遍历目标公司层级集合
        for (UserGroupLevelDTO dstLevel : dstLevels) {
            // 比较层级名称
            if (groupLevelMap.get(dstLevel.getGroupLevelName()) != null) {
                IdRelationDTO idRelation = IdRelationDTO.builder()
                        .oldId(groupLevelMap.get(dstLevel.getGroupLevelName()).getGroupLevelId())
                        .newId(dstLevel.getGroupLevelId())
                        .build();

                idRelations.add(idRelation);
            }
        }

        return idRelations;
    }

    /**
     * 比较目标公司组织和源公司组织的seq + groupLevelId , 并返回一致的
     *
     * @param dstOrgId
     * @param levelIdRelationList
     * @param srcGroups
     * @return
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/1/21 16:30
     */
    private List<IdRelationDTO> buildGroupIdRelations(String dstOrgId, List<IdRelationDTO> levelIdRelationList, List<UserGroupDTO> srcGroups) {
        // 查询目标公司组织
        ServiceResult<List<UserGroupDTO>> dstServiceResult = userGroupService.listByOrgId(dstOrgId);
        // 设置返回值
        List<IdRelationDTO> idRelations = new ArrayList<>();
        if (!dstServiceResult.isSuccess()) {
            return idRelations;
        }
        if (CollectionUtils.isEmpty(dstServiceResult.getData())) {
            return idRelations;
        }
        // 遍历源公司组织集合
        Map<String, IdRelationDTO> groupLevelMap = levelIdRelationList.stream()
                .collect(Collectors.toMap(IdRelationDTO::getOldId, item -> item));
        // dstGroupSeqMap
        Map<Integer, List<UserGroupDTO>> dstGroupSeqMap = dstServiceResult.getData().stream()
                .filter(s -> s.getSeq() != null)
                .collect(Collectors.groupingBy(UserGroupDTO::getSeq));

        for (UserGroupDTO srcGroup : srcGroups) {
            IdRelationDTO levelIdRelation = groupLevelMap.get(srcGroup.getGroupLevelId());
            if (levelIdRelation == null) {
                continue;
            }
            // 查询目标公司组织: 通过源公司id + groupLevelId + seq
            List<UserGroupDTO> dstGroups = dstGroupSeqMap.get(srcGroup.getSeq());
            if (CollectionUtils.isEmpty(dstGroups) || !levelIdRelation.getNewId().equals(dstGroups.get(0).getGroupLevelId())) {
                continue;
            }

            IdRelationDTO idRelation = IdRelationDTO.builder()
                    .oldId(srcGroup.getGroupId())
                    .newId(dstGroups.get(0).getGroupId())
                    .build();

            idRelations.add(idRelation);
        }

        return idRelations;
    }

    /**
     * 参数校验-开放平台的层级更新
     *
     * @param param 参数
     * @return
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/2/21 10:47
     */
    private ServiceResult<String> updateOpenGroupTreeCheck(OpenGroupTreeParam param) {
        // 1.基础参数格式校验
        ServiceResult<Object> serviceResult = ValidatorUtil.validateFast(param);
        if (!serviceResult.isSuccess()) {
            ServiceResult<String> result = ServiceResult.fail(serviceResult.getMsg());
            result.setErrorCode(serviceResult.getErrorCode());
            return result;
        }

        // 2.其他参数格式校验
        // 2.1 层级参数校验
        Set<String> levelNameSet = new HashSet<>();
        Set<Integer> levelNumSet = new HashSet<>();
        Map<String, Integer> levelMap = new HashMap<>();
        Integer firstLevelNum = null;
        String firstLevelName = null;
        for (GroupLevelSyncParam level : param.getLevels()) {
            // 层级名称不能重复
            if (levelNameSet.contains(level.getName())) {
                return doDataError(UserErrorMsgEnum.OPEN_API_LEVEL_NAME_REPECT, level.getName());
            }
            // 校验层级名称格式
            if (GroupLevelUtil.checkLevelNameInvalid(level.getName())) {
                return doDataError(UserErrorMsgEnum.OPEN_API_LEVEL_NAME_FORMAT, level.getName());
            }
            levelNameSet.add(level.getName());

            // 层级数不能重复
            if (levelNumSet.contains(level.getLevel())) {
                return doDataError(UserErrorMsgEnum.OPEN_API_LEVEL_NUM_REPECT, level.getLevel());
            }
            levelNumSet.add(level.getLevel());

            levelMap.put(level.getName(), level.getLevel());

            if (firstLevelNum == null) {
                firstLevelNum = level.getLevel();
            } else {
                firstLevelNum = level.getLevel().compareTo(firstLevelNum) < 0 ? level.getLevel() : firstLevelNum;
            }
            firstLevelName = firstLevelNum.equals(level.getLevel()) ? level.getName() : firstLevelName;
        }

        // 2.2 组织参数校验
        // 组织编码Set-重复校验使用
        Set<String> groupCodeSet = new HashSet<>();
        // 是否存在根节点
        boolean hasRoot = false;
        // 组织编码List
        Map<String, List<GroupSyncParam>> groupMap = param.getGroups().stream().collect(Collectors.groupingBy(GroupSyncParam::getCode));
        for (GroupSyncParam group : param.getGroups()) {
            // 组织编码不能重复
            if (groupCodeSet.contains(group.getCode())) {
                return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_CODE_REPECT, group.getCode());
            }
            groupCodeSet.add(group.getCode());

            // 组织的层级名称不存在层级集合
            if (!levelNameSet.contains(group.getLevelName())) {
                return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_LEVEL_NOT_FOUND, group.getLevelName());
            }

            if (group.getRootFlag() != null && group.getRootFlag()) {
                // 不能同时有两个根节点
                if (hasRoot) {
                    return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_ROOT_EXCEED);
                }
                hasRoot = true;

                // 根节点的所属层级应该为第一层
                if (!levelMap.get(group.getLevelName()).equals(firstLevelNum)) {
                    return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_ROOT_LEVEL_WRONG, group.getCode(), firstLevelName);
                }

                // 根节点的parent_code应为空
                if (StringUtils.isNotBlank(group.getParentCode())) {
                    return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_PARENT_NOT_NULL);
                }
                // 设置根节点parentCode为空字符串
                group.setParentCode(StringUtils.EMPTY);

            } else if (StringUtils.isBlank(group.getParentCode())) {
                // 非根节点的parent_code不能为空
                return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_PARENT_NULL);
            } else if (groupMap.get(group.getParentCode()) == null) {
                // 上级组织code 找不到对应的组织
                return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_PARENT_NULL, group.getParentCode());
            } else {
                // 循环嵌套校验
                Integer childLevelNum = levelMap.get(group.getLevelName());
                String parentLevelName = groupMap.get(group.getParentCode()).get(0).getLevelName();
                Integer parentLevelNum = levelMap.get(parentLevelName);
                if (childLevelNum.compareTo(parentLevelNum) <= 0) {
                    return doDataError(UserErrorMsgEnum.OPEN_API_GROUP_RELATION_NEST, group.getCode());
                }
                // 设置父组织的层级名称
                group.setParentLevelName(parentLevelName);
            }

        }

        return ServiceResult.success();
    }

    /**
     * 设置出错饭后信息
     *
     * @param errorMsgEnum 错误信息提示常量枚举
     * @param params       错误参数
     * @return ServiceResult<String>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/2/21 10:47
     */
    private ServiceResult<String> doDataError(UserErrorMsgEnum errorMsgEnum, Object... params) {
        String errorMsg = MessageFormat.format(errorMsgEnum.getMsg(), params);
        return ServiceResult.fail(errorMsgEnum.getCommonErrorEnum(), errorMsg);
    }
}
